// Author: Bjorn Schobben

#include <algorithm>
#include "LineSegment.h"

using std::max;
using std::min;

LineSegment::LineSegment(Point newp0, Point newp1): p0(newp0), p1(newp1)
{
}

LineSegment::LineSegment()
{
}

LineSegment::~LineSegment()
{
}

void LineSegment::SetLine(Point newp0, Point newp1)
{
	p0 = newp0;
	p1 = newp1;
}

//Check if the linesegment contains the parameter point
bool LineSegment::Contains(const Point& point) const
{
	bool contains = false;

	int xmin = min(p0.GetX(), p1.GetX());
	int xmax = max(p0.GetX(), p1.GetX());
	int ymin = min(p0.GetY(), p1.GetY());
	int ymax = max(p0.GetY(), p1.GetY());

	// check if the point lies in the rectangle determined by p0 & p1
	if (xmin <= point.GetX() && point.GetX() <= xmax && ymin <= point.GetY() && point.GetY() <= ymax)
	{
		// special case for vertical line
		if (p0.GetX() == p1.GetX())
		{
			if (point.GetX() == p0.GetX())
			{
				contains = true;
			}
		}
		// else check if the point fits the analytic equation of a line determined by 2 points (y - y0 = (y1 - y0) / (x1 - x0) * (x - x0))
		else if ((point.GetY() - p0.GetY()) * (p1.GetX() - p0.GetX()) == (p1.GetY() - p0.GetY()) * (point.GetX() - p0.GetX()))
		{
			contains = true;
		}
	}

	return contains;
}

//Check if the parameter line and the local line overlap in any way
bool LineSegment::OverlapsWith(const LineSegment& line) const
{
	bool overlap = false;
	int commonPoints = 0;

	//The following 4 if-tests will check if the the end points of 1 linesegement contained within the other and count them.
	if(line.Contains(p0))
	{
		commonPoints++;
	}
	if(line.Contains(p1))
	{
		commonPoints++;
	}
	if(Contains(line.p0))
	{
		commonPoints++;
	}
	if(Contains(line.p1))
	{
		commonPoints++;
	}
	
	/*In case the algorithm accounted for 2 unique points, the lines will overlap. But when both linesegments have
	  at least 1 endpoint in common, the algorithm will count both end points while only the unique points need to be
	  counted, resulting in an incorrect result when both linesegments have 1 endpoint in common, yet they don't overlap.
	  Our algorithms corrects this flaw by augmenting the condition of succes in case of common end points.*/
	if(p0 == line.p0 || p1 == line.p1 || p0 == line.p1 || p1 == line.p0)
	{
		if(commonPoints >= 3)
		{
			overlap = true;
		}
	}
	else
	{
		if(commonPoints >= 2)
		{
			overlap = true;
		}
	}
		
	return overlap;
}

//Test if 2 linesegments are equal
bool LineSegment::operator==(const LineSegment& rhs) const
{
	return((p0 == rhs.p0 && p1 == rhs.p1) || (p0 == rhs.p1 && p1 == rhs.p0));
}